package errors

import (
    "github.com/pkg/errors"
)

type ErrCode int32

func (m ErrCode) Error() string {
    if s, ok := code2String[m]; ok {
        return s
    } else {
        return code2String[Unknown]
    }
}

func New(err ErrCode) error {
    return errors.WithStack(err)
}

func Cause(err error) error {
    return errors.Cause(err)
}

func Wrap(err error, message string) error {
    return errors.Wrap(err, message)
}

func WithMessage(err error, message string) error {
    return errors.WithMessage(err, message)
}

func WithStack(err error) error {
    return errors.WithStack(err)
}

func GetErrorCode(err error) ErrCode {
    if code, ok := errors.Cause(err).(ErrCode); ok {
        return code
    } else {
        return Unknown
    }
}

var code2String = map[ErrCode]string{
    Canceled:           "Canceled",
    Unknown:            "Unknown",
    InvalidArgument:    "Invalid Argument",
    DeadlineExceeded:   "DeadlineExceeded",
    NotFound:           "Not Found",
    AlreadyExists:      "Already Exists",
    PermissionDenied:   "Permission Denied",
    ResourceExhausted:  "Resource Exhausted",
    FailedPrecondition: "Failed Precondition",
    Aborted:            "Aborted",
    OutOfRange:         "Out Of Range",
    Unimplemented:      "Unimplemented",
    Internal:           "Internal",
    Unavailable:        "Unavailable",
    DataLoss:           "Data Loss",
    Unauthenticated:    "Unauthenticated",
}

const (
    Canceled           = ErrCode(1)
    Unknown            = ErrCode(2)
    InvalidArgument    = ErrCode(3)
    DeadlineExceeded   = ErrCode(4)
    NotFound           = ErrCode(5)
    AlreadyExists      = ErrCode(6)
    PermissionDenied   = ErrCode(7)
    ResourceExhausted  = ErrCode(8)
    FailedPrecondition = ErrCode(9)
    Aborted            = ErrCode(10)
    OutOfRange         = ErrCode(11)
    Unimplemented      = ErrCode(12)
    Internal           = ErrCode(13)
    Unavailable        = ErrCode(14)
    DataLoss           = ErrCode(15)
    Unauthenticated    = ErrCode(16)
)
